
#include <mutex>
#include <atomic>

/*
* std::atomic_thread_fence(std::memory_order_acquire); 
* std::atomic_thread_fence(std::memory_order_release);
* 这两句话可以保证他们之间的语句不会发生乱序执行。
*/
/*
获得是一个对内存的读操作，当前线程的任何后面的读写操作都不允许重排到这个操作的前面去。
释放是一个对内存的写操作，当前线程的任何前面的读写操作都不允许重排到这个操作的后面去。

acquire 和 release 通常都是配对出现的，目的是保证如果对同一个原子对象的 release 发生在 acquire 之前的话，release 之前发生的内存修改能够被 acquire 之后的内存读取全部看到。
*/
class Singleton
{
public:
	Singleton* GetInstance();

	class CGarbo
	{
	public:
		~CGarbo()
		{
			if(Singleton::p)
				delete Singleton::p;
		}
	};
	static CGarbo garbo;//定义一个静态成员变量，程序结束时，系统会自动调用它的析构函数从而释放单例对象

private:
	static std::atomic<Singleton*> p;
	Singleton() = default;
	std::mutex mutex_;// new
};
Singleton* Singleton::p = nullptr;

//C++11之前的多线程下，不一定正确。原因在于在C++11之前的标准中并没有规定local static变量的内存模型。于是乎它就是不是线程安全的了。
Singleton *Singleton::GetInstance() {
    static singleton p;
    return &p;
}